/* generator */

/* function */
function foo(x) {
    return x + x;
}

/* generator */
function* foo(x) {
    yield x + 1;
    yield x + 2;
    return x + 3;
}


/* fibo */
/* function */
function fibo(max) {
    var
        t,
        a = 0,
        b = 1,
        arr = [0, 1];
    while (arr.length < max) {
        [a, b] = [b, a + b];
        arr.push(b);
    }


    return arr;
}

fibo(5);    // [0, 1, 1, 2, 3]

/* generator */
function* fibo_g(max) {
    var
        t,
        a = 0,
        b = 1,
        n = 0;
    while (n < max) {
        yield a;
        [a, b] = [b, a + b];
        n++;
    }
    return;
}

fibo_g(5);  // fibo_g {<suspended>}

var f = fibo_g(5);
f.next();   // {value: 0, done: false}
f.next();   // {value: 1, done: false}
f.next();   // {value: 1, done: false}
f.next();   // {value: 2, done: false}
f.next();   // {value: 3, done: false}
f.next();   // {value: undefined, done: true}


var arr = [];
for (var x of fibo_g(10)) {
    arr.push(x);
}
arr;    // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]


var fib = {
    a: 0,
    b: 1,
    n: 0,
    max: 5,
    next: function () {
        var
            r = this.a,
            t = this.a + this.b;
        this.a = this.b;
        this.b = this.t;
        if (this.n < this.max) {
            this.n++;
            return r;
        } else {
            return undefined;
        }
    }
};

function* next_id() {
    var current_id = 0;
    while (1) {
        yield ++current_id;
    }
}

g = next_id();
g.next()    // {value: 1, done: false}
g.next()    // {value: 2, done: false}